/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.frontendproject.pageflow;

import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.exception.MetadataNotFoundException;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.web.appconfig.api.entity.GspAppConfig;
import com.inspur.edp.web.appconfig.core.service.GspAppConfigService;
import com.inspur.edp.web.common.JITEngineConstants;
import com.inspur.edp.web.common.constant.WebCommonExceptionConstant;
import com.inspur.edp.web.common.customexception.WebCustomException;
import com.inspur.edp.web.common.entity.TerminalType;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.common.logger.WebLogger;
import com.inspur.edp.web.common.metadata.GspProjectUtility;
import com.inspur.edp.web.common.metadata.MetadataGetterParameter;
import com.inspur.edp.web.common.metadata.MetadataTypeEnum;
import com.inspur.edp.web.common.metadata.MetadataUtility;
import com.inspur.edp.web.common.utility.ResourceLocalizeUtil;
import com.inspur.edp.web.common.utility.StringUtility;
import com.inspur.edp.web.frontendproject.constant.I18nExceptionConstant;
import com.inspur.edp.web.frontendproject.constant.I18nMsgConstant;
import com.inspur.edp.web.frontendproject.entity.ChosenFormList;
import com.inspur.edp.web.jitengine.JITEngineManager;
import com.inspur.edp.web.pageflow.metadata.entity.AdaptedPageFlowMetadataEntity;
import com.inspur.edp.web.pageflow.metadata.entity.AdaptedPageFlowMetadataEntityService;
import com.inspur.edp.web.pageflow.metadata.entity.Page;
import com.inspur.edp.web.pageflow.metadata.entity.PageFlowMetadataEntity;
import com.inspur.edp.web.pageflow.metadata.service.PageFlowMetadataUpdateService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.nio.file.Paths;
import java.util.ArrayList;

/**
 * 页面流元数据manager
 *
 * @author guozhiqi
 */
public class PageFlowMetadataManager {

    private PageFlowMetadataManager() {
    }

    /**
     * 过滤指定的表单集合
     */
    public static PageFlowMetadataEntity filterPageFlowPages(PageFlowMetadataEntity pageFlowMetadataEntity, ChosenFormList buildFormList) {
        // 如果过滤的表单集合为空或个数为空 那么认为不进行过滤
        if (buildFormList == null || buildFormList.isEmpty()) {
            return pageFlowMetadataEntity;
        }
        // 定义一个新的页面流实体
        Object tempVar = pageFlowMetadataEntity.clone();
        PageFlowMetadataEntity filterPageFlowMetadataEntity = (PageFlowMetadataEntity) ((tempVar instanceof PageFlowMetadataEntity) ? tempVar : null);
        if (filterPageFlowMetadataEntity == null) {
            return pageFlowMetadataEntity;
        }

        ArrayList<Page> pageList = new ArrayList<>();
        for (int i = 0; i < pageFlowMetadataEntity.getPages().length; i++) {
            Page pageItem = pageFlowMetadataEntity.getPages()[i];
            String formCode = pageItem.getCode();
            // 区分大小写
            if (buildFormList.contains(formCode)) {
                pageItem.setForceDynamicForm(buildFormList.getIsDynamicFormByFormCode(formCode));
                pageList.add(pageItem);
            }
        }

        filterPageFlowMetadataEntity.setPages(pageList.toArray(new Page[0]));
        return filterPageFlowMetadataEntity;
    }


    /**
     * 获取或创建对应的页面流
     */
    public static PageFlowMetadataEntity getPageFlowEntityList(String projectPath, GspAppConfig appConfigInfo, TerminalType terminalType) {
        PageFlowMetadataEntity pageFlowMetadataEntity = null;

        if (!checkIfStorePageFlowId(projectPath, appConfigInfo, terminalType)) {
            pageFlowMetadataEntity = createPageFlowEntity(projectPath, terminalType);
        } else {
            GspMetadata pageFlowMetadata = getPageFlowMetadata(projectPath, appConfigInfo, terminalType);
            if (pageFlowMetadata == null) {
                pageFlowMetadataEntity = null;
            } else {
                pageFlowMetadataEntity = (PageFlowMetadataEntity) (pageFlowMetadata.getContent());
            }

            // 兼容没有页面流元数据的场景
            if (pageFlowMetadataEntity == null) {
                pageFlowMetadataEntity = createPageFlowEntity(projectPath, terminalType);
            }
        }

        return pageFlowMetadataEntity;
    }

    /**
     * 保存页面流元数据内容至工程目录下
     *
     * @param pageFlowMetadataEntity
     * @param targetStorageBasePath
     * @param terminalType
     */
    public static void saveRouteMetadata(PageFlowMetadataEntity pageFlowMetadataEntity, String targetStorageBasePath, TerminalType terminalType) {
        String projectName = GspProjectUtility.getProjectName(targetStorageBasePath);

        AdaptedPageFlowMetadataEntity adaptedPageFlowMetadataEntity = AdaptedPageFlowMetadataEntityService.generateAdaptedPageFlowMetadataEntity(pageFlowMetadataEntity);
        String metadataContent = AdaptedPageFlowMetadataEntityService.serialize(adaptedPageFlowMetadataEntity);

        String projectFormRelativeResolvePath = JITEngineManager.getProjectFormRelativeResolvePath(terminalType, false);
        if (adaptedPageFlowMetadataEntity.getPages() != null && !adaptedPageFlowMetadataEntity.getPages().isEmpty()) {
            FileUtility.writeFile(Paths.get(targetStorageBasePath).resolve(projectFormRelativeResolvePath).toString(), projectName + JITEngineConstants.ProjectRouteFileExtension, metadataContent);
        }
    }

    private static boolean checkIfStorePageFlowId(String projectPath, GspAppConfig appConfigInfo, TerminalType terminalType) {
        boolean alreadyStoragedPageFlowId = true;
        switch (terminalType) {
            case PC:
                if (StringUtility.isNullOrEmpty(appConfigInfo.getPageFlowMetadataID())) {
                    alreadyStoragedPageFlowId = false;
                }
                break;
            case MOBILE:
                if (StringUtility.isNullOrEmpty(appConfigInfo.getMobilePageFlowMetadataID())) {
                    alreadyStoragedPageFlowId = false;
                }
                break;
            default:
                throw new WebCustomException(WebCommonExceptionConstant.WEB_COMMON_ERROR_0010, new String[]{String.valueOf(terminalType)});
        }
        return alreadyStoragedPageFlowId;
    }

    /**
     * 创建页面流元数据（没有表单时不创建，返回null）
     */
    private static PageFlowMetadataEntity createPageFlowEntity(String projectPath, TerminalType terminalType) {

        // (1) 创建元数据
        GspMetadata routeMetadata = PageFlowMetadataUpdateService.getInstance().createRouteMetadataInMemory(projectPath, terminalType);
        PageFlowMetadataEntity pageFlowMetadataEntity = (PageFlowMetadataEntity) routeMetadata.getContent();
        if (pageFlowMetadataEntity.getPages().length == 0) {
            return null;
        }

        // (2) 持久化页面流元数据
        String routeMetadataRelativePath = PageFlowMetadataUpdateService.getInstance().createRouteMetadataInDisk(routeMetadata);

        // (3) 回写appconfigInfo
        GspAppConfigService.getCurrent().updateAppConfigFile(terminalType, routeMetadata.getHeader().getId(), routeMetadata.getHeader().getFileName(), routeMetadataRelativePath);

        return pageFlowMetadataEntity;
    }

    private static GspMetadata getPageFlowMetadata(String projectPath, GspAppConfig appConfigInfo, TerminalType terminalType) {
        // 获取元数据前，更新元数据上下文
        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
        metadataService.setMetadataUri(projectPath);

        String pageFlowMetadataID = "";
        switch (terminalType) {
            case PC:
                pageFlowMetadataID = appConfigInfo.getPageFlowMetadataID();
                break;
            case MOBILE:
                pageFlowMetadataID = appConfigInfo.getMobilePageFlowMetadataID();
                break;
            default:
                throw new WebCustomException(WebCommonExceptionConstant.WEB_COMMON_ERROR_0010, new String[]{String.valueOf(terminalType)});
        }
        // 判断元数据是否存在
        try {
            MetadataGetterParameter metadataGetterParameter = MetadataGetterParameter.getNewInstance(pageFlowMetadataID, projectPath, MetadataTypeEnum.Route);
            metadataGetterParameter.setTargetMetadataNotFoundMessage(ResourceLocalizeUtil.getString(I18nMsgConstant.WEB_FRONT_PROJECT_MSG_0001));

            GspMetadata pageFlowMetadata = MetadataUtility.getInstance().getMetadataWithDesign(metadataGetterParameter);
            return pageFlowMetadata;
        } catch (MetadataNotFoundException ex) {
            // 如果捕获到元数据找不到异常 那么重新进行元数据的创建

            WebLogger.Instance.info(ResourceLocalizeUtil.getString(I18nMsgConstant.WEB_FRONT_PROJECT_MSG_0002, appConfigInfo.getPageFlowMetadataID()), PageFlowMetadataManager.class.getName());
            return null;
        }

    }
}
